package org.rui.rpc.proxy;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetClient;
import io.vertx.core.net.NetSocket;
import org.rui.RpcApplication;
import org.rui.rpc.config.RpcConfig;
import org.rui.rpc.constant.ProtocolConstant;
import org.rui.rpc.constant.RpcConstant;
import org.rui.rpc.enums.ProtocolMessageSerializerEnum;
import org.rui.rpc.enums.ProtocolMessageTypeEnum;
import org.rui.rpc.model.RpcRequest;
import org.rui.rpc.model.RpcResponse;
import org.rui.rpc.model.ServiceMetaInfo;
import org.rui.rpc.protocol.ProtocolMessage;
import org.rui.rpc.protocol.ProtocolMessageDecoder;
import org.rui.rpc.protocol.ProtocolMessageEncoder;
import org.rui.rpc.registry.Registry;
import org.rui.rpc.registry.RegistryFactory;
import org.rui.rpc.serializer.Serializer;
import org.rui.rpc.serializer.SerializerFactory;
import org.rui.rpc.server.tcp.VertxTcpClient;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * 服务代理（JDK 动态代理）,存在rpc端，便于给消费者提供代理服务
 * 如果通过动态代理方式调用的话，就会执行对应的代理增强，如构造http请求并携带序列化好的rpcRequest
 * 交给http请求处理器HttpServerHandler.java 执行请求处理获得响应结果，代理在接着反序列化获得响应结果
 */
public class ServiceProxy implements InvocationHandler {

    /**
     * 调用代理
     *
     * @return
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        // 指定序列化器
        //Serializer serializer = new JdkSerializer();
        //根据配置文件的指定序列化器加载，避免硬编码
        RpcConfig rpcConfig = RpcApplication.getRpcConfig();
        Serializer serializer = SerializerFactory.getSerializer(rpcConfig.getSerializer());
        // 构造请求
        RpcRequest rpcRequest = RpcRequest.builder()
                .serviceName(method.getDeclaringClass().getName())
                .methodName(method.getName())
                .parameterTypes(method.getParameterTypes())
                .args(args)
                .build();
        try {
            // 序列化
            byte[] bodyBytes = serializer.serialize(rpcRequest);
            //获取配置中的注册中心
            Registry registry = RegistryFactory.getInstance(rpcConfig.getRegistryConfig().getRegistry());
            //封装注册信息
            ServiceMetaInfo serviceMetaInfo = new ServiceMetaInfo();

            serviceMetaInfo.setServiceName(method.getDeclaringClass().getName());
            serviceMetaInfo.setServiceVersion(RpcConstant.DEFAULT_SERVICE_VERSION);
            //根据注册信息寻找服务提供者注册的服务地址集合
            List<ServiceMetaInfo> serviceMetaInfos = registry.serviceDiscovery(serviceMetaInfo.getServiceKey());
            if (CollUtil.isEmpty(serviceMetaInfos)) {
                throw new RuntimeException("暂时没有服务地址");
            }
            //这里先默认取第一个服务地址
            ServiceMetaInfo info = serviceMetaInfos.get(0);
           /* // 发送请求
            try (HttpResponse httpResponse = HttpRequest.post(info.getServiceAddress())
                    .body(bodyBytes)
                    .execute()) {
                byte[] result = httpResponse.bodyBytes();
                // 反序列化
                RpcResponse rpcResponse = serializer.deserialize(result, RpcResponse.class);
                return rpcResponse.getData();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }*/
            // 发送 TCP 请求
            RpcResponse rpcResponse = VertxTcpClient.doRequest(rpcRequest, info);
            return rpcResponse.getData();
        } catch (Exception e) {
            throw new RuntimeException("调用失败");
        }
    }
}
